package vh.android.multiconnector.library;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URISyntaxException;

import vh.android.multiconnector.library.model.ClientListener;
import vh.android.multiconnector.library.model.ServerListener;
import android.content.Intent;
import android.util.Log;

/**
 * For handling incoming messages from a client.
 * 
 * @author Robert Hahn
 * 
 */
public class ConnectionHandler extends Thread implements Runnable {

	private static final String LOG_TAG = ConnectionHandler.class.getName();
	public static final String CHANNEL_ACTION = "vh.android.multiconnector.CHANNEL";
	private Socket mClientSocket;
	private ServerListener mServerListener;
	private String mID;
	private boolean mTimedout = false;
	private ClientListener mClientListener;

	public ConnectionHandler(String pID, ServerListener pListener,
			Socket pClientSocket) {
		this.mID = pID;
		this.mServerListener = pListener;
		this.mClientSocket = pClientSocket;
	}

	public ConnectionHandler(String pIP, ClientListener pListener,
			Socket pClientSocket) {
		this.mID = pIP;
		this.mClientListener = pListener;
		this.mClientSocket = pClientSocket;
	}

	@Override
	public void run() {
		try {
			BufferedReader in = new BufferedReader(new InputStreamReader(
					mClientSocket.getInputStream()));
			String message;
			while ((message = in.readLine()) != null) {
				Intent intent = null;
				try {
					intent = Intent.parseUri(message, 0);
				} catch (URISyntaxException e) {
					continue;
				}
				if (intent == null) {
					continue;
				}
				// packet has illegal action -> drop it
				if (!intent.getAction().startsWith(
						ConnectionHandler.CHANNEL_ACTION)) {
					// intent has corrupted action
					Log.e(LOG_TAG, "intent has corrupted action");
					continue;
				}

				// valid packet for this application
				if (mServerListener != null)
					mServerListener.onClientMessageReceived(mClientSocket,
							intent);
				if (mClientListener != null)
					mClientListener.onServerMessageReceived(mID, intent);
				Log.d(LOG_TAG, "received channel packet");
			}
		} catch (SocketTimeoutException e) {
			// ping wasnt received -> client disconnected
			mTimedout = true;
			if (mServerListener != null)
				mServerListener.onClientTimedout(mClientSocket);
			if (mClientListener != null)
				mClientListener.onServerTimedout(mID);
			Log.e(LOG_TAG, "Client timedout");
			// close connection
			try {
				mClientSocket.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}

			// TODO try to reconnect
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public boolean isTimedout() {
		return mTimedout;
	}

}
